---
title: 'shadow | Cypress Documentation'
description: Traverse into the shadow DOM of an element in Cypress.
sidebar_label: shadow
slug: /api/commands/shadow
---

<ProductHeading product="app" />

# shadow

Traverse into the shadow DOM of an element.

## Syntax

```javascript
.shadow()
.shadow(options)
```

### Usage

<Icon name="check-circle" color="green" /> **Correct Usage**

```javascript
cy.get('.shadow-host').shadow()
```

<Icon name="exclamation-triangle" color="red" /> **Incorrect Usage**

```javascript
cy.shadow() // Errors, cannot be chained off 'cy'
cy.exec('npm start').shadow() // Errors, 'exec' does not yield DOM element
cy.get('.not-a-shadow-host').shadow() // Errors, subject must host a shadow root
```

### Arguments

<Icon name="angle-right" /> **options _(Object)_**

Pass in an options object to change the default behavior of `.shadow()`.

| Option    | Default                                                           | Description                                                                         |
| --------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| `log`     | `true`                                                            | Displays the command in the [Command log](/app/core-concepts/open-mode#Command-Log) |
| `timeout` | [`defaultCommandTimeout`](/app/references/configuration#Timeouts) | Time to wait for `cy.get()` to resolve before [timing out](#Timeouts)               |

<HeaderYields />

- `.shadow()` yields the new DOM element(s) it found.
- `.shadow()` is a query, and it is _safe_ to chain further commands.

## Examples

### Find and click on a button inside the shadow DOM

```html
<div class="shadow-host">
  #shadow-root
  <button class="my-button">Click me</button>
</div>
```

```javascript
// yields [#shadow-root (open)]
cy.get('.shadow-host').shadow().find('.my-button').click()
```

## Rules

<HeaderRequirements />

- `.shadow()` requires being chained off a command that yields a DOM element
  that is a shadow host (i.e. has a shadow root directly attached to it).

<HeaderAssertions />

- `.shadow()` will automatically [retry](/app/core-concepts/retry-ability)
  until the element(s)
  [exist in the DOM](/app/core-concepts/introduction-to-cypress#Implicit-Assertions).
- `.shadow()` will automatically [retry](/app/core-concepts/retry-ability)
  until the element(s) host(s) a shadow root.
- `.shadow()` will automatically [retry](/app/core-concepts/retry-ability)
  until all chained assertions have passed.

<HeaderTimeouts />

- `.shadow()` can time out waiting for the element(s) to
  [exist in the DOM](/app/core-concepts/introduction-to-cypress#Implicit-Assertions).
- `.shadow()` can time out waiting for the element(s) to host a shadow root.
- `.shadow()` can time out waiting for assertions you've added to pass.

## Known Issue

When working with `cy.click()`, it sometimes won't click the right element in
Chrome. It's happening because of
[the ambiguity in spec](https://bugs.chromium.org/p/chromium/issues/detail?id=1188919&q=shadowRoot%20elementFromPoint&can=2).

In this case, pass `'top'` to `cy.click()` like below:

```js
cy.get('#element').shadow().find('[data-test-id="my-button"]').click('top')
```

## Command Log

**_Traverse into the shadow DOM of an element_**

```javascript
cy.get('.shadow-host').shadow()
```

The commands above will display in the Command Log as:

<DocsImage
  src="/img/api/shadow/shadow-command-log.png"
  alt="Command Log shadow"
/>

When clicking on the `shadow` command within the command log, the console
outputs the following:

<DocsImage
  src="/img/api/shadow/shadow-in-console.png"
  alt="console.log shadow"
/>

## See also

- [`cy.get()`](/api/commands/get#Arguments) with `includeShadowDom` option
- [`cy.find()`](/api/commands/find#Arguments) with `includeShadowDom` option
- [`cy.contains()`](/api/commands/contains#Arguments) with `includeShadowDom`
  option
- [`includeShadowDom` config option](/app/references/configuration#Global)
